<template>
  <vue-modal
    @submitData="saveNotice"
    modalTitle="保存公告信息"
    modalName="saveNoticeModal"
    modalWidth="750"
    ref="saveNoticeModal">
    <div slot="content" class="form-box">
      <el-form ref="form" :model="form" label-width="80px">
        <div class="message-box">
          <h3 class="content-title">公告内容</h3>
          <span :class="showContentTip? 'content-tip showTip': 'content-tip'">长度不超过50个字符</span>
          <p class="content-star">*</p>
        </div>
        <el-input
          v-model="form.content"
          class="input-name"
          size="small"
          maxlength="50"
          @focus="focusContentInput"
          @blur="blurContentInput"></el-input>
        <div class="message-box">
          <h3 class="link-title">链接</h3>
          <span :class="errorMsg? 'link-tip showTip': 'link-tip'">{{errorMsg}}</span>
        </div>
        <el-input
          v-model="form.link"
          class="input-link"
          size="small"></el-input>
        <div class="tool-button-box">
          <el-button @click="form.link = ''" type="info" size="medium">清空</el-button>
          <el-button @click="form.link = 'http://'" type="" size="medium">还原</el-button>
          <el-button @click="urlTest" type="primary" size="medium" :disabled="disableTestButtonFlag">测试链接</el-button>
        </div>
        <div class="message-box">
          <h3 class="type-title">公告类型</h3>
          <p class="type-star">*</p>
        </div>
        <el-select v-model="form.type" placeholder="请选择所属分类" class="select-category" size="small">
          <el-option
            v-for="item in typeData"
            :key="item.type"
            :label="item.label"
            :value="item.type">
          </el-option>
        </el-select>
        <div class="message-box">
          <h3 class="usable-title">是否启用</h3>
          <p class="usable-star">*</p>
          <span :class="disabledUsableRadioFlag? 'usable-tip showTip': 'usable-tip'">
            已达到了可启用的{{form.type? typeData[form.type - 1].label: ''}}的上限
          </span>
        </div>
        <el-radio-group v-model="form.usable" size="medium">
          <el-radio-button label="1" :disabled="disabledUsableRadioFlag">可用</el-radio-button>
          <el-radio-button label="0">禁用</el-radio-button>
        </el-radio-group>
      </el-form>

    </div>
  </vue-modal>
</template>

<script>

  import VueModal from 'components/common/modal/VueModal';

  import {insertNotice, updateNotice, getNoticeCountByType} from "../../../network/viewsRequest/notice";

  import {MIN_LENGTH_OF_URL, IMAGE_SERVER_URL, MANAGE_SERVER_URL, PATH_PORTAL_PLACEHOLDER,
    PORTAL_SERVER_URL, MAX_COUNT_OF_USABLE_NOTICE} from "../../../common/const";

  export default {
    name: "SaveNoticeTemplate",
    data() {
      return {
        form: {
          id: 0,
          content: '',
          type: null,
          link: 'http://',
          usable: 0,
          linkHandled: '', // 处理后的链接信息，即保存的link字段
        },
        typeData: [{
          type: 1,
          label: '前端页面公告'
        }, {
          type: 2,
          label: '管理后台公告'
        }],
        errorMsg: '', // 链接的错误信息
        disabledUsableRadioFlag: false, // 是否需要禁用“可用”按钮的标记
        showContentTip: '', // 是否显示输入框的提示信息
      }
    },
    methods: {
      show() {
        this.form = {id: 0, link: 'http://'};
        this.errorMsg = '';
        this.$refs.saveNoticeModal.show();
      },
      closeModal() {
        this.$refs.saveNoticeModal.closeModal();
      },
      /**
       * 当内容输入框获得焦点时，显示输入的提示信息
       */
      focusContentInput() {
        this.showContentTip = true;
      },
      /**
       * 当内容输入框失去焦点时，隐藏输入的提示信息
       */
      blurContentInput() {
        this.showContentTip = false;
      },
      /**
       * 保存公告的方法
       */
      saveNotice() {
        // 1.校验输入信息
        if (!this.validArguments()) {
          return;
        }
        /*
         * 2.对form.link进行处理，逻辑如下：
         *    2.1.当链接是本后台项目或者后台服务器的链接，不允许
         *    2.2.当链接是前台项目的链接，为了以后迁移数据的方便，要将前台项目的主机名改为占用符后进行保存
         *    2.3.当以“http://”或“https://”开头时不进行保存
         *    2.4.当不是上面两种情况，并且输入的内容也不是可以测试的url字符串时提示用户所输入的url可能不合法，是否继续保存
         *    2.5.其他情况正常保存
         **/
        if (this.form.link.startsWith(MANAGE_SERVER_URL) || this.form.link.startsWith(IMAGE_SERVER_URL)) {
          // 2.1.当链接是本后台项目或者后台服务器的链接，不允许
          this.$message({
            type: 'error',
            message: '本管理后台或服务器地址不能作为公告的链接地址！'
          });
          return;
        } else if (this.form.link.startsWith(PORTAL_SERVER_URL)) {
          // 2.2.当链接是前台项目的链接，为了以后迁移数据的方便，要将前台项目的主机名改为占用符后进行保存
          this.form.linkHandled = PATH_PORTAL_PLACEHOLDER + this.form.link.substring(PORTAL_SERVER_URL.length);
          // 调用方法进行保存
          this.openConfirm("确定要保存吗？");
        } else if (this.form.link === 'http://' || this.form.link === 'https://') {
          // 2.3.当以“http://”或“https://”开头时不进行保存
          this.form.linkHandled = '';
          // 调用方法进行保存
          this.openConfirm("确定要保存吗？");
        } else if (!this.enableTestButtonFlag()) {
          // 2.4.当不是上面两种情况，并且输入的内容也不是可以测试的url字符串时提示用户所输入的url可能不合法，是否继续保存
          this.openConfirm("您输入的链接可能不合法，是否继续保存？");
        } else {
          // 2.5.其他情况正常保存
          this.form.linkHandled = this.form.link;
          this.openConfirm("确定要保存吗？");
        }
      },
      /**
       * 打开确认框进行保存
       */
      openConfirm(message) {
        this.$confirm(message, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'info'
        }).then(() => {
          // 调用方法进行保存
          this.saveNoticeLogic();
        }).catch(() => {
          this.$message({
            type: 'info',
            message: '保存的操作已经取消'
          });
        });
      },
      /**
       * 新增操作和更新操作的参数校验方法
       * 即对content、type和usable三者的非空校验
       */
      validArguments() {
        if (this.form.content === undefined || this.form.content.length === 0) {
          this.$message({
            type: 'error',
            message: '请输入公告内容'
          });
          return false;
        }

        if (this.form.type === undefined) {
          this.$message({
            type: 'error',
            message: '请选择公告类型'
          });
          return false;
        }

        if (this.form.usable === undefined) {
          this.$message({
            type: 'error',
            message: '请选择公告是否启用'
          });
          return false;
        }

        return true;
      },
      /**
       * 具体进行保存的逻辑代码
       */
      saveNoticeLogic() {
        // 1.选择处理方法
        let func = null;
        if (this.form.id === 0) {
          func = insertNotice;
        } else {
          func = updateNotice;
        }

        // 2.进行处理
        func(this.form).then(res => {
          if (res.code == 1) {
            this.$message({
              type: 'success',
              message: '保存成功',
            });
            this.closeModal();
            this.$emit("reloadTable");
          } else {
            this.$message({
              type: 'error',
              message: res.message,
            });
          }
        })
      },
      /**
       * 点击“测试”按钮调用的方法
       */
      urlTest() {
        window.open(this.form.link);
      },
      /**
       * 判断一个字符串是否是可以测试的url
       * @returns {boolean}
       */
      enableTestButtonFlag() {
        let url = this.form.link;
        let startFlag = false;
        let endFlag = false;

        if (url) {
          // 当url是本管理后台的地址或者是远程服务器的地址，按钮禁用
          if (url.indexOf(IMAGE_SERVER_URL) > -1 || url.indexOf(MANAGE_SERVER_URL) > -1) {
            this.errorMsg = '本管理后台或服务器地址不能作为公告的链接地址';
            return false;
          }
          // 当url是localhost的链接时，按钮直接启用
          if (url.indexOf("http://localhost") > -1 || url.indexOf("https://localhost") > -1) {
            this.errorMsg = '';
            return true;
          }
          // 当url是初始的http://时，虽然按钮时禁用，但是不显示错误信息
          if (url === "http://") {
            this.errorMsg = '';
            return false;
          }
          // 当url的长度大于最小长度，并且是以“http://”或者“https://”开头的话，startFlag就为true
          if (url.length >= MIN_LENGTH_OF_URL && (url.startsWith("http://") || url.startsWith("https://"))) {
            startFlag = true;
          }
          // 当url中包含字符'.'的时候，endFlag就为true
          if (url.indexOf('.') > -1) {
            endFlag = true;
          }
          // 当startFlag和endFlag都为true时，按钮时启用状态
          if (startFlag && endFlag) {
            this.errorMsg = '';
            return true;
          }
        }
        this.errorMsg = '输入的url不合法';
        return false;
      },
      /**
       * 判断是否需要禁用“可用”选项
       *    当type对应的可用公告超过最大数量时，“可用”的选项被禁用
       *    当type对应的可用公告没有超过最大数量时，“可用”的选项启用
       */
      disabledUsableRadio(val) {
        getNoticeCountByType(val).then(res => {
          if (res.code == 1) {
            if (res.data >= MAX_COUNT_OF_USABLE_NOTICE && this.form.usable !== 1) {
              this.disabledUsableRadioFlag = true;
            } else {
              this.disabledUsableRadioFlag = false;
            }
          } else {
            this.disabledUsableRadioFlag = false;
          }
        })
      },
      /**
       * 根据父组件中传递过来noticeFromParent的值进行信息的回显
       * @param notice 父组件中传递过来的用于回显的公告信息
       */
      assignFormFromParent(notice) {
        /*
         * 在回显的时候系统会对type值修改两次，分别为：
         *    1.打开模态框的时候，会将form的信息清空，这也导致了form.type会被清空
         *    2.调用此方法的时候会修改form.type
         *  由于两个方法不是同步执行，所以在时间上会有出入，会有如下的结果：
         *    1.如果情况1先执行，情况2后执行，那么回显是没有问题的
         *    2.如果情况2先执行，情况1后执行，那么回显就会失败
         *  为此，给情况2，就是本方法的调用推迟0.1s后再执行
         */
        window.setTimeout(() => {
          this.form.id = notice.id;
          this.form.content = this.$set(this.form, "content", notice.content);
          this.form.type = this.$set(this.form, "type", notice.type);
          if (notice.link && notice.link.indexOf(PATH_PORTAL_PLACEHOLDER) > -1) {
            notice.link = PORTAL_SERVER_URL + notice.link.substring(notice.link.length);
          }
          this.form.link = this.$set(this.form, "link", notice.link || "http://");
          this.form.usable = this.$set(this.form, "usable", notice.usable);
          this.form.linkHandled = this.$set(this.form, "linkHandled", '');
        }, 100)
      },
    },
    props: {
      noticeFromParent: {
        type: Object,
        default: function() {
          return {}
        }
      }
    },
    components: {
      VueModal
    },
    computed: {
      disableTestButtonFlag() {
        // 当输入的字符串不是一个可以测试的url时，disableFlag为true，即把测试按钮禁用
        return !this.enableTestButtonFlag();
      }
    },
    watch: {
      // 对type进行监控，实时判断“可用”按钮是否进行禁用
      "form.type": function(val) {
        this.disabledUsableRadio(val);
      },
      noticeFromParent: {
        deep: true,
        handler(val) {
          // 回显信息
          this.assignFormFromParent(val);
        }
      }
    }
  }
</script>

<style scoped>
  .form-box {
    padding-left: 100px;
    position: relative;
  }
  .form-box p {
    position: absolute;
    color: #F56C6C;
  }
  .content-star {
    top: 0px;
    left: 178px;
  }
  .type-star {
    top: 230px;
    left: 178px;
  }
  .usable-star {
    top: 322px;
    left: 178px;
  }
  .input-name,.input-link {
    width: 500px;
  }
  h3 {
    display: inline-block;
    margin-bottom: 10px;
  }
  .link-title,.type-title,.usable-title {
    margin-top: 25px;
  }
  .content-tip,.link-tip,.usable-tip {
    margin-left: 20px;
    color: #F56C6C;
    visibility: hidden;
  }
  .message-box .showTip {
    visibility: visible;
  }

  /*.input-description {*/
    /*margin-bottom: 10px;*/
  /*}*/
  .tool-button-box {
    margin-top: 10px;
    display: flex;
    justify-content: left;
  }
</style>
